#include "../common/config.h"
#include "httpconfig.h"

using namespace std;

RuleBase::RuleBase() : m_src(NULL), m_dst(NULL)
{}

RuleBase::RuleBase(const RuleBase & r)
{
	if(r.m_src != NULL)
		m_src = r.m_src->clone();
	else
		m_src = NULL;

	if(r.m_dst != NULL)
		m_dst = r.m_dst->clone();
	else
		m_dst = NULL;
}

RuleBase::~RuleBase()
{
	if(m_src != NULL)
		delete m_src;
	if(m_dst != NULL)
		delete m_dst;
}

RuleBase& RuleBase::operator=(const RuleBase & r)
{
	if(this != &r)
	{
		if(m_src != NULL)
		{
			delete m_src;
			m_src = NULL;
		}

		if(m_dst != NULL)
		{
			delete m_dst;
			m_dst = NULL;
		}
		
		if(r.m_src != NULL)
			m_src = r.m_src->clone();
		if(r.m_dst != NULL)
			m_dst = r.m_dst->clone();
	}

	return *this;
}

boost::shared_ptr<hippolib::host> RuleBase::getSource()
{
	if(m_src != NULL)
		return boost::shared_ptr<hippolib::host>(m_src->clone());
	return boost::shared_ptr<hippolib::host>();
}

bool RuleBase::setSource(const string & expr)
{
	hippolib::host *host;

	host = getHost(expr);
	if(host == NULL)
		return false;

	if(m_src != NULL)
		delete m_src;
	m_src = host;
	return true;
}

boost::shared_ptr<hippolib::host> RuleBase::getDestination()
{
	if(m_dst != NULL)
		return boost::shared_ptr<hippolib::host>(m_dst->clone());
	return boost::shared_ptr<hippolib::host>();
}

bool RuleBase::setDestination(const string & expr)
{
	hippolib::host *host;

	host = getHost(expr);
	if(host == NULL)
		return false;

	if(m_dst != NULL)
		delete m_dst;
	m_dst = host;
	return true;
}

hippolib::host* RuleBase::getHost(const string & expr)
{
	hippolib::host *ret = NULL;

	hippolib::iphost iphost;
	if((ret = iphost.create(expr)) != NULL)
		return ret;
	
	hippolib::nethost nethost;
	if((ret = nethost.create(expr)) != NULL)
		return ret;
	
	hippolib::iprangehost iprhost;
	if((ret = iprhost.create(expr)) != NULL)
		return ret;

	hippolib::namehost namehost;
	if((ret = namehost.create(expr)) != NULL)
		return ret;

	return ret;
}

AccessRule::AccessRule()
{}

AccessRule::AccessRule(const AccessRule & r) : RuleBase(r)
{
	m_action = r.m_action;
}

AccessRule::~AccessRule()
{}

AccessRule& AccessRule::operator=(const AccessRule & r)
{
	if(this != &r)
	{
		m_action = r.m_action;
		RuleBase::operator=(r);
	}

	return *this;
}

int AccessRule::getAction()
{
	return m_action;
}

void AccessRule::setAction(int action)
{
	m_action = action;
}

UpstreamProxy::UpstreamProxy() : m_name(""), m_host(""), m_port(0)
{}

UpstreamProxy& UpstreamProxy::operator=(const UpstreamProxy & p)
{
	if(this != &p)
	{
		m_name = p.m_name;
		m_host = p.m_host;
		m_port = p.m_port;
	}
	return *this;
}

std::string UpstreamProxy::getName() const
{
	return m_name;
}

void UpstreamProxy::setName(const std::string & name)
{
	m_name = name;
}

std::string UpstreamProxy::getHost() const
{
	return m_host;
}

void UpstreamProxy::setHost(const std::string & host)
{
	m_host = host;
}

unsigned short UpstreamProxy::getPort() const
{
	return m_port;
}

void UpstreamProxy::setPort(unsigned short port)
{
	m_port = port;
}

UpstreamRule::UpstreamRule()
{}

UpstreamRule::UpstreamRule(const UpstreamRule & rule) : RuleBase(rule)
{
	m_proxyname = rule.m_proxyname;
}

UpstreamRule::~UpstreamRule()
{}

UpstreamRule& UpstreamRule::operator=(const UpstreamRule & r)
{
	if(this != &r)
	{
		m_proxyname = r.m_proxyname;
		RuleBase::operator=(r);
	}
	return *this;
}

std::string UpstreamRule::getProxyName() const
{
	return m_proxyname;
}

void UpstreamRule::setProxyName(const std::string & name)
{
	m_proxyname = name;
}

LogConfig::LogConfig()
	: m_name(""), m_filename(""), m_level("warn"), m_backupindex(3)
{
}

LogConfig::LogConfig(const LogConfig & config)
{
	m_name = config.m_name;
	m_filename = config.m_filename;
	m_level = config.m_level;
	m_backupindex = config.m_backupindex;
}

LogConfig& LogConfig::operator=(const LogConfig & config)
{
	if(this != &config)
	{
		m_name = config.m_name;
		m_filename = config.m_filename;
		m_level = config.m_level;
		m_backupindex = config.m_backupindex;
	}

	return *this;
}

#define DEFAULT_LISTENING_PORT			8080
#define DEFAULT_WORKING_THREADS			10
#define DEFAULT_HEADER_MAXSIZE			4096
#define DEFAULT_USERNAME					""
#define DEFAULT_GROUPNAME					""
#define DEFAULT_WEB_PORT					7777

HTTPConfig::HTTPConfig()
		: m_listening_address(boost::asio::ip::address_v4::loopback()),
		m_listening_port(DEFAULT_LISTENING_PORT),
		m_threads(DEFAULT_WORKING_THREADS),
		m_header_buffer_maxsz(DEFAULT_HEADER_MAXSIZE),
		m_isauthenabled(false),
		m_isupstreamenabled(false),
		m_isaccess_rule_enabled(false),
		m_access_default_action(AccessRule::ALLOW),
		m_web_enabled(false),
		m_web_listenaddr(boost::asio::ip::address_v4::loopback()),
		m_web_listenport(DEFAULT_WEB_PORT),
		m_web_docroot(".")
{}

HTTPConfig::~HTTPConfig()
{}

HTTPConfig::HTTPConfig(const HTTPConfig & config)
{
	m_listening_address = config.m_listening_address;
	m_listening_port = config.m_listening_port;
	m_hostname = config.m_hostname;
	m_threads = config.m_threads;
	m_proc_username = config.m_proc_username;
	m_proc_groupname = config.m_proc_groupname;
	m_header_buffer_maxsz = config.m_header_buffer_maxsz;
	m_isauthenabled = config.m_isauthenabled;
	m_userdbs = config.m_userdbs;
	m_singleusers = config.m_singleusers;
	m_upstream_proxies = config.m_upstream_proxies;
	m_isupstreamenabled = config.m_isupstreamenabled;
	m_upstream_rules = config.m_upstream_rules;
	m_isaccess_rule_enabled = config.m_isaccess_rule_enabled;
	m_access_default_action = config.m_access_default_action;
	m_access_rules = config.m_access_rules;

	// log settings
	m_log_enabled = config.m_log_enabled;
	m_proxylog = config.m_proxylog;
	m_accesslog = config.m_accesslog;
	m_debugger = config.m_debugger;

	// web-based gui settings
	m_web_enabled = config.m_web_enabled;
	m_web_listenaddr = config.m_web_listenaddr;
	m_web_listenport = config.m_web_listenport;
	m_web_docroot = config.m_web_docroot;
}

HTTPConfig & HTTPConfig::operator=(const HTTPConfig & config)
{
	if(this != &config)
	{
		m_listening_address = config.m_listening_address;
		m_listening_port = config.m_listening_port;
		m_hostname = config.m_hostname;
		m_threads = config.m_threads;
		m_proc_username = config.m_proc_username;
		m_proc_groupname = config.m_proc_groupname;
		m_header_buffer_maxsz = config.m_header_buffer_maxsz;
		m_isauthenabled = config.m_isauthenabled;
		m_userdbs = config.m_userdbs;
		m_singleusers = config.m_singleusers;
		m_upstream_proxies = config.m_upstream_proxies;
		m_isupstreamenabled = config.m_isupstreamenabled;
		m_upstream_rules = config.m_upstream_rules;
		m_isaccess_rule_enabled = config.m_isaccess_rule_enabled;
		m_access_default_action = config.m_access_default_action;
		m_access_rules = config.m_access_rules;
		
		// log settings
		m_log_enabled = config.m_log_enabled;
		m_proxylog = config.m_proxylog;
		m_accesslog = config.m_accesslog;
		m_debugger = config.m_debugger;

		// web-based gui settings
		m_web_enabled = config.m_web_enabled;
		m_web_listenaddr = config.m_web_listenaddr;
		m_web_listenport = config.m_web_listenport;
		m_web_docroot = config.m_web_docroot;
	}

	return *this;
}

boost::asio::ip::address HTTPConfig::getListeningAddress() const
{
	return m_listening_address;
}

unsigned short HTTPConfig::getListeningPort() const
{
	return m_listening_port;
}

void HTTPConfig::setHostname(const string & hostname)
{
	m_hostname = hostname;
}

string HTTPConfig::getHostname() const
{
	return m_hostname;
}

size_t HTTPConfig::getThreads() const
{
	return m_threads;
}

size_t HTTPConfig::getMaxHeaderBufferSize() const
{
	return m_header_buffer_maxsz;
}

vector<std::string> HTTPConfig::getUserDBFilename() const
{
	return m_userdbs;
}

vector<HTTPUser> HTTPConfig::getUsers() const
{
	return m_singleusers;
}

bool HTTPConfig::isAuthEnabled() const
{
	return m_isauthenabled;
}

vector<UpstreamProxy> HTTPConfig::getUpstreamProxies() const
{
	return m_upstream_proxies;
}

bool HTTPConfig::isUpstreamEnabled() const
{
	return m_isupstreamenabled;
}

vector<UpstreamRule> HTTPConfig::getUpstreamRules() const
{
	return m_upstream_rules;
}

bool HTTPConfig::isAccessRuleEnabled() const
{
	return m_isaccess_rule_enabled;
}

int HTTPConfig::getAccessRuleDefaultAction() const
{
	return m_access_default_action;
}

vector<AccessRule> HTTPConfig::getAccessRules() const
{
	return m_access_rules;
}

string HTTPConfig::getProcUsername() const
{
	return m_proc_username;
}

string HTTPConfig::getProcGroupname() const
{
	return m_proc_groupname;
}

bool HTTPConfig::isLogEnabled() const
{
	return m_log_enabled;
}

LogConfig HTTPConfig::getProxyLogConfig()
{
	return m_proxylog;
}

LogConfig HTTPConfig::getAccessLogConfig()
{
	return m_accesslog;
}

LogConfig HTTPConfig::getDebuggerConfig()
{
	return m_debugger;
}

bool HTTPConfig::isWebEnabled() const
{
	return m_web_enabled;
}

boost::asio::ip::address HTTPConfig::getWebListeningAddress() const
{
	return m_web_listenaddr;
}

unsigned short HTTPConfig::getWebListeningPort() const
{
	return m_web_listenport;
}

std::string HTTPConfig::getWebDocRoot() const
{
	return m_web_docroot;
}
